############################################################################################
## gamelogic.py
##
## This file contains the core game logic for pewpewpew
##
## @author(s): CommisGordon
## @documentation: Shadow
##
## Created on October 22, 2009
############################################################################################
import pygame,gameroot,player,network,math,gamegraphics,ai,pane,ui,physics,loaders,dialogs


######################################################################################
## Game
##
## This class contains the core game logic
##
## @author(s): CommisGordon
## @documentation: Shadow
######################################################################################
class Game (pane.Pane):
	
	###########################################################
	## Game::__init__
	##
	## Constructor for the Game class
	## Desc: Initializes all of the variables
	###########################################################
	def __init__(self,root):
		pane.Pane.__init__(self,root)
		# surface to draw on
		self.surface = pygame.display.get_surface()
		# our ship
		self.player = player.Player(root,gameroot.respath+"ships/demoplayer.png")
		# collection of enemies
		self.enemies = []
		# collection of bullets
		self.bullets = []
		# collection of controls
		self.controls = []
		# current focus of control (game or chat)
		self.focus = "game"
		# ai controller producer
		self.factory = None
		# the physics handler
		self.physics = physics.CollisionHandler()
		# the audio handler
		self.root.audiosys.set_bgm(loaders.load_sound(gameroot.respath+"music/morrowind.ogg"))
		
		
		
		#init the screen and camera
		self.gameScreen = gamegraphics.GameScreen(self.root)
		self.uiScreen = ui.UIScreen(self.root)
		self.gameCamera = gamegraphics.GameCamera(self.root)
		
		#initialize the in-game user interface elements
		self.minimap = ui.Minimap(self.root,self.gameCamera,self.enemies);
		self.mainmap = ui.Mainmap(self.root,self.gameCamera,self.enemies);
		self.displayNames = ui.DisplayNames(self.root,self.gameCamera,self.enemies);
		self.displayChat = ui.DisplayChat(self.root);
		self.displayLeaderboard = ui.DisplayLeaderboard(self.root);
		self.displayHealth = ui.DisplayHealth(self.root,self.gameCamera,self.enemies);
		
		#the zoom of the current screen
		self.gameCamera.zoom = .5
		
		#add player to the gameScreen collection
		self.gameScreen.addGameDrawable(self.player)
		
		#add the ui elements to the uiScreen collection
		self.uiScreen.addUIDrawable(self.minimap)
		self.uiScreen.addUIDrawable(self.mainmap)
		self.uiScreen.addUIDrawable(self.displayNames)
		self.uiScreen.addUIDrawable(self.displayChat)
		self.uiScreen.addUIDrawable(self.displayLeaderboard)
		self.uiScreen.addUIDrawable(self.displayHealth)
		self.uiScreen.addUIDrawable(ui.UIMeters(self.root))
		
		#make our cursor visible
		self.cursoralwaysvisible=True
		
	#####################	 END __init__	 ####################
		
		
	###########################################################
	## Game::update
	##
	## Function to update several game mechanics
	## Delegate updates to controls, player visual, and enemy visuals
	###########################################################
	def update(self):
		#update the main pane were drawing on
		pane.Pane.update(self)
		#tick time along...
		time=self.root.gameclock.get_time()
		
		#update
		if self.dialog==None:
			#handle in game controls
			self.handlecontrol()
			#open a menu if we hit the cancel button (esc by default)
			if self.root.monitor.getjustpressed(self.root.prefs["key_cancel"]):
			 	self.dialog=dialogs.PauseDialog(self.root)
		
		#update the physical player movemenr
		self.player.update(time)
		
		#make the camera follow the player
		self.gameCamera.xpos = self.player.xpos
		self.gameCamera.ypos = self.player.ypos
		
		#get chat messages, then pass them into displayChat's update()
		self.displayChat.update(self.factory.getChatMessages())

		
		#grab any new enemies from our factory (in case a player joined the game)
		temps = self.factory.getNew()
		for e in temps:
			self.enemies.append(e)
			self.gameScreen.addGameDrawable(e)
			
		#grab al the bullets shot since the last frame
		temps = self.factory.getNewBullets()
		for b in temps:
			self.bullets.append(b)
			self.gameScreen.addGameDrawable(b)
		
		#remove any enemies that have been gone a while
		temps = self.factory.getRemove()
		removals = []
		for e in self.enemies:
			if e.pid in temps:
				self.gameScreen.removeGameDrawable(e)
				removals.append(e)
		for e in removals:
			self.enemies.remove(e)
			print "Player has disconnected - "+str(e.pid)
		
		#remove old bullets too
		temps = self.factory.getRemoveBullets()
		removals = []
		for b in self.bullets:
			if b.bid in temps or b.recycle:
				self.gameScreen.removeGameDrawable(b)
				removals.append(b)
		for b in removals:
			self.bullets.remove(b)

		#update all the other players	
		for e in self.enemies:
			e.update(time)
			
		#update all the bullets
		for b in self.bullets:
			b.update(time)
		
		#make physics happen (collisions)
		self.physics.update(self.enemies, self.player,self.bullets)
	######################	 END update	 #####################
	
	
	###########################################################
	## Game::repaint
	##
	## Function to update all game visuals
	## Paint the background and the player and the cursor etc
	###########################################################
	def repaint(self):
		
		#draw all GameDrawables
		self.gameScreen.renderScreen(self.gameCamera)
		
		#draw all UIDrawables
		self.uiScreen.renderScreen()

		#draw any menus
		pane.Pane.repaint(self)

	######################	 END repaint	 #####################
	
	
	###########################################################
	## Game::handlecontrol
	##
	## 
	## TDesc: handles the controls of the game (like chatting and moving/shooting)
	###########################################################
	def handlecontrol(self):
		
		## if game has focus have all controls affect the players ship
		if self.focus == "game":
			#turn off the message for chat
			self.displayChat.visible = False
			
			#toggleable ui options
			self.displayHealth.update(self.gameCamera, self.enemies,self.root.monitor.getjustpressed("B"))
			self.minimap.update(self.gameCamera, self.enemies,self.root.monitor.getjustpressed("N"))
			self.mainmap.update(self.gameCamera, self.enemies,self.root.monitor.getjustpressed("M"))
			self.displayNames.update(self.gameCamera, self.enemies,self.root.monitor.getjustpressed("V"))
			self.displayLeaderboard.update(self.factory.getLeaderboard(),self.root.monitor.getjustpressed("L"))
			
			#if they hit enter then switch to chat mode
			if(self.root.monitor.getjustpressed("RETURN")): 
				self.focus = "chat"
			else:
				self.player.handleControls()
			
		## if in chat mode grab all control for message input ##
		elif self.focus == "chat":
			#turn on the message for chat
			self.displayChat.visible = True
			
			#if they hit enter then send the message they typed and give the control ack to the ship
			if(self.root.monitor.getjustpressed("RETURN")): 
				self.focus = "game"
				self.factory.appendChatMessage(self.displayChat.currentMessage)
				self.displayChat.currentMessage=""
			else:
				self.displayChat.handleControls()

##################	 END handlecontrol	 ##################
	
###################################	 END Game	 #####################################

 

######################################################################################
## SoloGame
##
## An extension of the Game class implementing single player gameplay
##
## @author(s): CommisGordon
## @documentation: Shadow
######################################################################################
class SoloGame(Game):
	###########################################################
	## Game::__init__
	##
	## Constructor for the SoloGame class
	## Desc: Initializes all of the variables
	###########################################################
	def __init__(self,root):
		Game.__init__(self, root)
		self.factory = ai.AIFactory(ai.SOLO_GAME,self.root,self.player)
	#####################	 END __init__	 ####################
	
#################################	 END SoloGame	 ###################################


######################################################################################
## NetworkGame
##
## An extension of the Game class implementing LAN gameplay
##
## @author(s): CommisGordon
## @documentation: Shadow
######################################################################################
class NetworkGame(Game):
	
	###########################################################
	## Game::__init__
	##
	## Constructor for the NetworkGame class
	## Desc: Initializes all of the variables
	###########################################################
	def __init__(self,root,username="Playername"):
		Game.__init__(self,root)
		self.username=username
		self.player.username = username
		self.factory = ai.AIFactory(ai.NETWORK_GAME,self.root,self.player)
	#####################	 END __init__	 ####################
	
###############################	 END NetworkGame	 ##################################


######################################################################################
## OnlineGame
##
## An extension of the Game class implementing online gameplay
##
## @author(s): CommisGordon
## @documentation: Shadow
######################################################################################
class OnlineGame(Game):
	
	###########################################################
	## Game::__init__
	##
	## Constructor for the OnlineGame class
	## Desc: Initializes all of the variables
	###########################################################
	def __init__(self,root):
		Game.__init__(self, root)
		self.factory = ai.AIFactory(ai.ONLINE_GAME,self.root,self.player)
		self.net = network.NetworkHandler()
		self.net.write(network.Packet(network.LOGIN_USERNAME,"user"))
		self.net.write(network.Packet(network.LOGIN_PASSWORD,"pass"))
	#####################	 END __init__	 ####################
	
	
	###########################################################
	## Game::handlecontrol
	##
	## NonDescript
	## TODO/FIX: This
	###########################################################
	def handlecontrol(self):
		p = self.net.read()
		pass
	##################	 END handlecontrol	 ##################
	
	
###############################	 END OnlineGame	 ###################################


####################################	 END gamelogic.py	 ##################################


		